package com.ecr.hub.front.bean.managed;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.ecr.hub.ApplicationException;
import com.ecr.hub.front.bean.AbstractManagedBean;
import com.ecr.hub.model.user.Role;
import com.ecr.hub.model.user.User;
import com.ecr.hub.service.user.IUserManager;
import com.ecr.hub.util.EncryptionUtils;
import com.ecr.hub.util.MessageUtils;

@Controller("userManaged")
@Scope("session")
public class UserManagedBean extends AbstractManagedBean {

	private static final long serialVersionUID = 1L;

	// La liste des utilisateurs.
	private List<User> lstUsers;
	// L'index de l'utilisateur sur lequel travaille le chef d'agence.
	private int currentUserIndex;
	// L'utilisateur courant sur lequel travaille le chef d'agence.
	private User currentUser;

	// Manager pour les ressources utilisateur.
	@Resource(name = "userManager")
	private transient IUserManager userManager;

	/**
	 * Génération de la liste complète des utilisateurs, ne pas oublier qu'une
	 * seule personne à la fois peut être connectée en écriture, ainsi, la liste
	 * présentée est à tous moments la représentation exacte de la base de
	 * données.
	 */
	@PostConstruct
	public void _getAllList() {
		try {
			setLstUsers(userManager.getAllList());
		} catch (Exception e) {
			getErrorHandler(e);
		}
	}

	/**
	 * Suppression de l'utilisateur dans la base de données. L'utilisateur
	 * courant est directement supprimé dans la liste, cela évite de faire un
	 * select pour rafraîchir la liste des utilisateurs.
	 */
	public void delete() {

		try {
			userManager.delete(lstUsers.get(currentUserIndex));
			lstUsers.remove(currentUserIndex);
			MessageUtils.setMessageInfo("user.deleted");
		} catch (Exception e) {
			getErrorHandler(e);
		}
	}

	/**
	 * Edition de l'utilisateur, soit en insertion, soit en modification, dans
	 * les deux cas, l'utilisateur courant est replacé dans la liste après
	 * opération en base de données, cela évite de faire un select pour
	 * rafraîchir la liste des utilisateurs. Dans le cas d'une création
	 * utilisateur, il faut en plus créer son répertoire de stockage pour les
	 * pdfs,on crée simplement un répertoire avec l'identifiant de
	 * l'utilisateur.
	 */
	public void edit() {

		try {
			// Insertion ou modification utilisateur.
			if ("update".equals(typeAction)) {

				userManager.update(currentUser);
				lstUsers.set(currentUserIndex, currentUser);
				MessageUtils.setMessageInfo("user.modified");

			} else if ("create".equals(typeAction)) {

				userManager.create(currentUser);
				lstUsers.add(currentUser);
				MessageUtils.setMessageInfo("user.created");
			}
		} catch (Exception e) {
			getErrorHandler(e);
		}
	}

	/**
	 * Validator interne au bean. Vérification du mot de passe, ce dernier doit
	 * être identique à la confirmation du mot de passe. De plus, il doit être
	 * unique dans la base. Ce validator est utilisé par le chef d'agence pour
	 * les créations et modifications utilisateur. On ne peut lancer la
	 * validation que si le login utilisateur est renseigné, puisqu'il sert de
	 * clé de cryptage. Pour un nouvel utilisateur, l'identifiant est égal à 0,
	 * il ne peut donc pas être trouvé dans la liste. Dans le cas ou le mot de
	 * passe n'a pas été modifié par l'administrateur, le cryptage du mot de
	 * passe déjà crypté fait qu'il ne peut pas être trouvé dans la liste, ce
	 * n'est donc pas génant pour passer la validation.
	 */
	public void passwordUniqueValidator(FacesContext context,
			UIComponent component, Object value) throws ValidatorException,
			ApplicationException {
		if (null != currentUser.getLogin()) {
			String encryptPassword = EncryptionUtils.encryptePassword(
					value.toString(), currentUser.getLogin());
			for (User user : lstUsers) {
				if ((user.getId() != currentUser.getId())
						&& (user.getPassword().equals(encryptPassword))) {
					throw new ValidatorException(
							MessageUtils
									.getMessageError("validator.password.notunique"));
				}
			}
		}
	}

	/**
	 * Validator interne au bean. Vérification du login utilisateur, ce dernier
	 * doit être unique en base de données.
	 */
	public void loginUniqueValidator(FacesContext context,
			UIComponent component, Object value) throws ValidatorException {
		for (User user : lstUsers) {
			if ((user.getId() != currentUser.getId())
					&& (user.getLogin().equals(value))) {
				throw new ValidatorException(
						MessageUtils
								.getMessageError("validator.login.notunique"));

			}
		}
	}

	// ****************************
	// Les getters et setters.
	// ****************************

	public List<User> getLstUsers() {
		return lstUsers;
	}

	public int getCurrentUserIndex() {
		return currentUserIndex;
	}

	public User getCurrentUser() {
		return currentUser;
	}

	public void setLstUsers(List<User> lstUsers) {
		this.lstUsers = lstUsers;
	}

	public void setCurrentUserIndex(int currentUserIndex) {
		this.currentUserIndex = currentUserIndex;
	}

	public void setCurrentUser(User currentUser) {
		this.currentUser = currentUser;
	}

	@Override
	public void setTypeAction(String typeAction) {
		if ("create".equals(typeAction))
			setCurrentUser(new User(new Role()));
		this.typeAction = typeAction;
	}
}
